// Copyright (C) 2008 Taylor L. Riche <riche@cs.utexas.edu>
//  
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
// 
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
// 
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software 
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
//

#ifndef PROCELEMENT_H_
#define PROCELEMENT_H_

#include <cstdlib>
#include <iostream>
#include <map>
#include <queue>

#include <errno.h>

#include "CommChannel.h"
#include "RCon.h"
#include "RData.h"
#include "MemGroup.h"

const unsigned int PROF_SIZE = 1000;

namespace lagniappe
{
	
class CommChannel;
class RCon;
class MemGroup;
class Application;

class ProcElement
{
protected:
	virtual RCon * getRCon() = 0;
	RCon * getProfRCon();
	bool freeze;
	bool inProfile;
	int group;
	std::queue<RCon *> profQueue;
	MemGroup * memGroup;
	std::vector<lagniappe::CommChannel *> sourceChannels;
	std::vector<lagniappe::CommChannel *>::iterator chanIter;

	std::map<lagniappe::ProcElement *, lagniappe::CommChannel *> chanMap;
	Application * app;
	std::string name;
	
public:
	ProcElement(bool profile, std::string n);
	virtual ~ProcElement();
	void process();
	virtual void processRequest(RCon * rc) = 0;
	virtual void init() = 0;
	virtual void destroy() = 0;
	virtual void addSrcChan(CommChannel * sc) = 0;
	virtual void addDestChan(ProcElement * p, CommChannel * dc) = 0;
	virtual bool isOverloaded(RCon * rc) = 0;
	virtual void unFreeze() = 0;
	virtual void getThread() = 0;
	virtual void startTimer() = 0;
	virtual double endTimer() = 0;
	inline void setGroup(int g) {group = g;}
	inline int getGroup() {return group;}
	void putProfRCon(RCon * rcon);
	virtual void profileWait() = 0;
	virtual void profileNotify() = 0;
	virtual void profileLock() = 0;
	virtual void profileUnlock() = 0;
	bool profileDone() {return profQueue.empty();}
	inline MemGroup * getMemGroup() const {return memGroup;}
	inline void setMemGroup(MemGroup * mg) {memGroup = mg;} 
	inline CommChannel * lookupDestChan(ProcElement * p) {return chanMap[p];}
	virtual bool isLocal() = 0;
	void setApp(Application * newApp) {app = newApp;}
	Application * getApp() {return app;}
	std::string getName() {return name;}
};

#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */

void * startProc(void * arg);

#ifdef __cplusplus
}
#endif /* __cplusplus */
  
  

}

#endif /*PROCELEMENT_H_*/
